using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml.Serialization;
using NETL.Engine.Data;
using NETL.Engine.Source;

namespace NETL.Engine.Destination
{
	public class BasicFileDestination : MessageDestinationBase
	{
		public enum ExistOperation
		{
			Append,
			OverWrite,
			Error
		}

		private bool myUseMessageName = true;
		private string myPath;
		private string myFileName;
		private ExistOperation myExistsOperation = ExistOperation.Error;

		public ExistOperation ExistsOperation
		{
			get { return myExistsOperation; }
			set { myExistsOperation = value; }
		}

		public string Path
		{
			get { return myPath; }
			set { myPath = value; }
		}

		public string FileName
		{
			get { return myFileName; }
			set { myFileName = value; }
		}

		/// <summary>
		/// Gets or sets a value indicating whether [use message name for file].
		/// </summary>
		/// <value>
		/// 	<c>true</c> if [use message name for file]; otherwise, <c>false</c>.
		/// </value>
		public bool UseMessageNameForFile
		{
			get { return myUseMessageName; }
			set { myUseMessageName = value; }
		}

		public override void Execute(IMessage message)
		{
			TextMessage textMessage = message as TextMessage;

			if (textMessage == null)
			{
				OnCompleted(new ExecutionResult(ExecutionStatus.InvalidConfiguration,
					String.Format("Message type is invalid, TextMessage required. ({0})", message.ToString())));
				return;
			}

			string file = textMessage.Name;
			if (!UseMessageNameForFile)
			{
				file = FileName;
			}

			try
			{
				FileInfo fInfo = new FileInfo(System.IO.Path.Combine(Path, file));

				if (fInfo.Exists)
				{
					if (ExistsOperation == ExistOperation.OverWrite)
					{
						Logger.DebugFormat("File \"{0}\" exists, deleting...", fInfo.FullName);
						fInfo.Delete();
					}
					else if (ExistsOperation == ExistOperation.Error)
					{
						OnCompleted(new ExecutionResult(ExecutionStatus.Failure, 
						                                String.Format("File \"{0}\" exists", fInfo.FullName)));
						return;
					}
				}

				if (fInfo.Exists)
				{
					using (StreamWriter writer = fInfo.AppendText())
					{
						writer.Write(textMessage.Data);
					}
				}
				else
				{
					using (StreamWriter writer = fInfo.CreateText())
					{
						writer.Write(textMessage.Data);
					}
				}
			}
			catch (Exception ex)
			{
				OnCompleted(new ExecutionResult(ExecutionStatus.Failure, ex.Message, ex));
				return;
			}


			OnCompleted(new ExecutionResult(ExecutionStatus.Success));
		}

		public override ExecutionResult Test()
		{
			if (Path == null)
			{
				return new ExecutionResult(ExecutionStatus.InvalidConfiguration,
					"Path is not set.");
			}

			DirectoryInfo dInfo = new DirectoryInfo(Path);

			if (!dInfo.Exists)
			{
				return new ExecutionResult(ExecutionStatus.InvalidConfiguration, 
					String.Format("Path \"{0}\" does not exist or is non-accessible.", Path));
			}

			if (!UseMessageNameForFile && (FileName == null || FileName.Length == 0))
			{
				return new ExecutionResult(ExecutionStatus.InvalidConfiguration, 
					"Using static filename, but filename is not set.");
			}

			return new ExecutionResult(ExecutionStatus.Success);
		}

	}
}
